/******************************************************************************
 *                     Organizacion de Datos - 75.06                          *
 *                         Catedra Lic. Servetto                              *
 *            Facultad de Ingenieria - Universidad de Buenos Aires            *
 ******************************************************************************/ 

#include "ManejadorEspacioLibre.h"
#include <fstream>
#include <iostream>

#define INDICADORES_POR_LINEA 32

namespace CapaFisica
{

	MapaDeBits::MapaDeBits(std::string clase, int tamanioRegistro) : ManejadorEspacioLibre(clase)
	{
		this->tamanioRegistro = tamanioRegistro;
		Inicializar();
	}

	MapaDeBits::~MapaDeBits()
	{		
	}

	bool MapaDeBits::EstaLibre(int grupoId)
	{
		// El bloque se encuentra libre si la extension es 0
		return elementos[grupoId] == 0;
	}

	bool MapaDeBits::EstaInicializado(int grupoId)
	{
		// El bloque se encuentra inicializado si la extension no es -1.
		return elementos[grupoId] != -1;

	}

	void MapaDeBits::Liberar(int grupoId)
	{
		// 0 significa vacio
		elementos[grupoId] = 0;
	}

	int MapaDeBits::ObtenerTamanio(int grupoId)
	{
		return this->tamanioRegistro;
	}

	void MapaDeBits::AsignarTamanio(int grupoId, int nuevoTamanio)
	{
		// No aplica para mapa de bits
	}
	
	long MapaDeBits::ObtenerTamanioArchivo()
	{
		long contador = 0;

		for ( int i=0 ; i < MAX_NUM_REGISTERS ; i++){
			//Si encuentra un elemento con -1, significa que llego al final del archivo
			if ( elementos[i] == -1)
				break;

			contador++;
		}

		return contador * tamanioRegistro;
	}
	
	int MapaDeBits::ObtenerBloqueLibre(int tamanio)
	{
		for ( int i=0 ; i < MAX_NUM_REGISTERS ; i++)
		{
			if (elementos[i] == 0){
				// 1 significa ocupado
				elementos[i] = 1;
				return i;
			}
			else if (elementos[i] == -1){
				// 1 significa ocupado
				elementos[i] = 1;
				return i;
			}
		}
		cerr << "CapaFisica->MapaDeBits.cpp->MapaDeBits::ObtenerBloqueLibre(int tamanio)" << endl << "Se utilizaron los " << MAX_NUM_REGISTERS << " disponibles para manejar el espacio libre." << endl;
		throw new exception();
	}
	
	void MapaDeBits::Inicializar()
	{
		int tamanioLinea = INDICADORES_POR_LINEA*2 + 1;
		char* buffer = new char[ tamanioLinea ];
		
		int contadorLinea = 0;

		// Inicializa el vector de bits a -1 (registro no instanciado)
		for ( int i=0 ; i < MAX_NUM_REGISTERS ; i++ )
			elementos[i]= -1;

		// Lee el archivo linea por linea
		while( file.getline( buffer, tamanioLinea ) )
		{
			for ( int i=0 ; i < INDICADORES_POR_LINEA ; i++ )
			{
				// Cada indicador ocupa 2 caracteres: '0' o '1' + ','
				char c = buffer[ i*2 ];

				// Si el caracter es de fin de linea, detiene la inicializacion
				if (c == 0)
					break;

				elementos[ contadorLinea*INDICADORES_POR_LINEA + i ] = CaracterADigito( c );
			}

			// Indica en que linea se encuentra la ejecucion
			contadorLinea++;
		}
	}

	void MapaDeBits::GuardarArchivo()
	{
		// Elimina los flags del archivo
		file.clear();
		// Se posiciona al principio del mismo
		file.seekg(0,ios_base::beg);

		bool finIndicadores = false;

		// Lectura de indicadores agrupados por INDICADORES_POR_LINEA
		for (int i=0; i < (MAX_NUM_REGISTERS / INDICADORES_POR_LINEA); i++)
		{
			if (finIndicadores)
				break;

			for ( int j=0 ; j<INDICADORES_POR_LINEA ; j++ )
			{	
				// Se llego al ultimo indicador
				if (elementos[i*INDICADORES_POR_LINEA + j] == -1)
				{
					finIndicadores = true;
					break;
				}
				
				file << elementos[ i*INDICADORES_POR_LINEA +j ] << ',';
				
			}
			file << endl;		
		}
	}

}
